//****************************************************************************
//
// lineIR_task.c
//
// Using PmodLS1 and the Fairchild QRB1134 IR proximity sensor, this 'task' 
// routine is inteded for use with the qs-autonomous simple task scheduler.
//
// There are 3 IR sensors along a straight edge accross the front of 
// EVALBOT. They are labelled 0, 1, 2 from left to right and hook into GPIO
// ports J4, J5, and J6, respectively. They output a logic 1 (+3.3V) when 
// actively sensing IR reflections. Else, they output a logic 0 (0V).
//
// The line has the following constraints:
//   - the line absorbs IR, while surrounding material reflects
//   - it's width is roughly the separation between IR sensors
//   - no corner turn is sharper than 90 degrees
//   - smooth curves are allowed
//
//****************************************************************************

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "lineIR_task.h"
#include "driverlib/gpio.h"

//****************************************************************************
//
// defines
//
//****************************************************************************
#define PROXIM_UP 1   // Logic level seen when positive detection (reflection)
#define PROXIM_DOWN 0 // Logic level seen when negative detection

//****************************************************************************
//
// Types and vars
//
//****************************************************************************
typedef struct {

  tBoolean bActive;
  unsigned long ulTicksInState;

} tProximSensor;

static tProximSensor g_sProximSensors[3];

//****************************************************************************
//
// Task to poll the 3 IR proximity sensors. Should be called from the 
// qs-autonomous simple task scheduler.
//
//****************************************************************************
void
LineIRTask(void *pvParam) {
  
  int proximVal;
  tBoolean bLastState;
  unsigned int uProxim; 
  
  // Read the sensors all at once
  proximVal = GPIOPinRead(GPIO_PORTJ_BASE,
			  GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6);

  for (uProxim = 0; uProxim < 3; uProxim++) {
    tProximSensor *pProxim = &g_sProximSensors[uProxim];

    // Save off last sensor state and grab the current state
    bLastState = pProxim->bActive;
    pProxim->bActive = ((proximVal >> (4+uProxim)) & 0x1);
    // Update the 'tick' counter for time in current state
    // 'Ticks' are relative to the polling interval and rate
    if (pProxim->bActive == bLastState) {
      pProxim->ulTicksInState += 1; 
    }
    else {
      pProxim->ulTicksInState = 0;
    }
  }
}

//****************************************************************************
//
// Return the sensor states as unsigned char. 
//
// Bits:   [7] [6] [5] [4] [3] [2] [1] [0]  
// Sensor:  X   X   X   X   X   3   2   1
//
// If a sensor detects the line (absence of light == false), return a 1 for 
// that sensor     
//
//****************************************************************************
unsigned char
getLineIRState(void) {

  unsigned char irState = 0;
  unsigned int uProxim;
  
  for (uProxim = 0; uProxim < 3; uProxim++) {
    tProximSensor *pProxim = &g_sProximSensors[uProxim];
    if (pProxim->bActive == false) {irState = irState | (0x1 << uProxim);}
  }

  return irState;

}

//****************************************************************************
//
// Function to initialize the three sensors. Must be called first
//
//****************************************************************************
void
LineIRInit(void) {

  unsigned int uProxim; 

  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
  GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, 
		       GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6);

  // Initialize all of the sensors to the inactive state
  for (uProxim = 0; uProxim < 3; uProxim++) {
    tProximSensor *pProxim = &g_sProximSensors[uProxim];

    pProxim->bActive = false; 
    pProxim->ulTicksInState = 0; 
  }

}
